﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GOFconsole
{
    public class Chapter23_Command
    {
        public void CommandTest()
        { 
            //模型
            Receiver r = new Receiver();
            Command c = new ConcreteCommand(r);//创建一个具体的命令对象，并设置它的接收者。
            Invoker i = new Invoker();

            i.SetCommand(c);
            i.ExecuteCommand();

            //Demo
            BBQer boy = new BBQer();
            Command_Demo bakeMutton1 = new BakeMuttonCommand(boy);
            Command_Demo bakeMutton2 = new BakeMuttonCommand(boy);
            Command_Demo bakeMutton3 = new BakeMuttonCommand(boy);
            Command_Demo bakeChicken = new BakeChickenWingCommand(boy);

            Waiter girl = new Waiter();
            //顾客点菜
            girl.SetOrder(bakeMutton1);
            girl.SetOrder(bakeMutton2);
            girl.SetOrder(bakeMutton3);
            girl.SetOrder(bakeChicken);
            girl.CancelOrder(bakeMutton3);  //取消一份

            //点菜完毕 通知厨房
            girl.Notify();
        }
    }

    #region 模型
    abstract class Command  //声明执行操作的接口
    {
        protected Receiver receiver;

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }
        abstract public void Execute();
    }
    class ConcreteCommand : Command //将一个接受者对象绑定于一个动作，调用接受者相应的操作，以实现Execute。
    {
        public ConcreteCommand(Receiver receiver)
            : base(receiver)
        { }

        public override void Execute()
        {
            receiver.Action();
        }
    }

    class Receiver  //知道如何实施与执行一个与请求相关的操作，任何类都可能作为一个接受者
    {
        public void Action()
        {
            Console.WriteLine("执行请求");
        }
    }
    class Invoker   //要求该命令执行这个请求
    {
        private Command command;

        public void SetCommand(Command command)
        {
            this.command = command;
        }

        public void ExecuteCommand()
        {
            command.Execute();
        }
    }

    #endregion

    #region DEMO(点烧烤)
    public class BBQer
    {
        public void BakeMutton()
        {
            Console.WriteLine("烤羊肉串");
        }
        public void BakeChickenWing()
        {
            Console.WriteLine("烤鸡翅膀");
        }
    }

    public abstract class Command_Demo  //抽象命令类
    {
        protected BBQer receiver;
        
        public Command_Demo(BBQer receiver)
        {
            this.receiver=receiver;
        }

        abstract public void ExecuteCommand();
    }
    public class BakeMuttonCommand:Command_Demo //烤羊肉命令实现类
    {
        public BakeMuttonCommand(BBQer receiver)
            :base(receiver)
        { }

        public override void ExecuteCommand()
        {
 	        receiver.BakeMutton();
        }
    }
     public class BakeChickenWingCommand:Command_Demo //烤鸡翅命令实现类
    {
        public BakeChickenWingCommand(BBQer receiver)
            :base(receiver)
        { }

        public override void ExecuteCommand()
        {
 	        receiver.BakeChickenWing();
        }
    }

    public class Waiter //服务员类
    { 
        private IList<Command_Demo> orders=new List<Command_Demo>();    //增加存放具体命令的容器

        public void SetOrder(Command_Demo command)  
        {
            orders.Add(command);
            //记录客户点的烧烤的日志，用来算钱
            Console.WriteLine("增加订单："+command.ToString()+"时间"+DateTime.Now.ToString());
        }
        public void CancelOrder(Command_Demo command)
        {
            orders.Remove(command);
            //记录客户点的烧烤的日志，用来算钱
            Console.WriteLine("取消订单：" + command.ToString() + "时间" + DateTime.Now.ToString());
        }

        public void Notify()
        {
            foreach (var item in orders)
            {
                item.ExecuteCommand();  //根据用户点好的订单通知厨房制作
            }
        }
    }

    #endregion

}
